
using System;
using System.Collections;
using Gnome;
using Gdk;

//using DiaCanvas;

namespace DiaCanvas
{
	
	public struct Color
	{
		public string ForeGround;
		public string BackGround;
		public string Select;
		public string Control;
	};
	
	public enum FiguraType { Conector, Circulo, Rectangulo, Rombo, Romboide };
	
	abstract public class Figura
	{
	
		private bool _debug = false;
	
		protected bool _bIn = false;
		protected bool _bDrag=false;
	
		protected bool _bControlPoint = false;
		protected bool _bResize = false;
	
		protected Gnome.Canvas _canvas;
		
		protected Gnome.CanvasShape _fig;
		
		protected Gdk.Point _oldPoint;
	
		protected Gdk.Point _point;
		protected Gdk.Point[] _points;
	
		#region "Puntos de Control"
		protected ArrayList _p;
		#endregion

		public DiaCanvas.Color _color;

		private uint _borderSize;
		
		
		public abstract FiguraType Type { get; }
		protected abstract Gnome.CanvasShape Shape { get; }
		
		virtual protected void DrawControlPoints()
		{
		
			for ( int i = 0 ; i < this._points.Length ; i++)
			{	
				int radio = 2;
				Gnome.CanvasEllipse e =  new Gnome.CanvasEllipse(this._canvas.Root()); 
				this._p.Add(e);
				e.X1 = ((Gdk.Point)this._points[i]).X-radio;
				e.Y1 = ((Gdk.Point)this._points[i]).Y-radio;
				e.X2 = ((Gdk.Point)this._points[i]).X+radio;
				e.Y2 = ((Gdk.Point)this._points[i]).Y+radio;
				
				e.OutlineColor = "#fff";//this.BackColor;
				e.FillColor = "#fff";//this.BackColor;
				
				e.WidthPixels = 5;//this.BorderSize;

				e.CanvasEvent += new Gnome.CanvasEventHandler(CanvasEvent);
				
				e.Hide();
			}
		}
		
		public Figura(Gnome.Canvas c)
		{
			
			this._color.ForeGround = "#000000";
			this._color.BackGround = "#000000";
			this._color.Select = "#00ff00";
			this._color.Control = "#00aa00"; 
					
			this._borderSize = 2;
			
			this._canvas = c;
			
			this._p = new ArrayList();
		}
		
		public abstract string toString();
		public abstract void draw();
		
		virtual protected void Move(EventButton ev)
		{
			double dx = ev.X - this._oldPoint.X;
			double dy = ev.Y - this._oldPoint.Y;
			
			this.Shape.Move(dx,dy);

			for ( int i = 0; i < this._p.Count; i++)
			{
				((Gnome.CanvasEllipse)this._p[i]).Move(dx,dy);
			}
			this._oldPoint.X = (int) ev.X;
			this._oldPoint.Y = (int) ev.Y;
		}
		
		abstract protected void Resize(Object obj, EventButton ev);
		
		protected virtual string ForeColor 
		{ 
			set { this._color.ForeGround = value; ChangeColor(); }
			get { return this._color.ForeGround;}
		}
		protected virtual string BackColor 
		{ 
			set { this._color.BackGround = value; ChangeColor(); } 
			get { return this._color.BackGround; }
		}
		protected virtual string SelectColor 
		{ 
			set { this._color.Select = value; ChangeColor(); }
			get { return this._color.Select; }
		}
		protected virtual string ControlColor 
		{ 
			set { this._color.Control = value; ChangeColor(); } 
			get { return this._color.Control; }
		}
		
		protected virtual uint BorderSize 
		{ 
			set { this._borderSize = value; } 
			get { return this._borderSize; }
		}
		
		public bool Debug
		{
			set { this._debug = value; }
			get { return this._debug; }
		}
		
		protected abstract void ChangeColor();
		
		protected abstract void CalculateControlPoints();
		
		private void ActivateControlPoints(bool hide)
		{
			
			for ( int i = 0; i < this._p.Count; i++)
			{	
				Gnome.CanvasEllipse p = ((Gnome.CanvasEllipse)this._p[i]);
				if ( ! hide ) 
					p.Show();
				else
					p.Hide();
			}
		}
		
		protected virtual void MouseEnter(object obj, Gnome.CanvasEventArgs args)
		{
			this._bIn = true;
			ActivateControlPoints(false);	
			this._bControlPoint = ( this._p.Contains(obj) );

			ChangeColor();
		}
		
		protected virtual void MouseLeave(object obj, Gnome.CanvasEventArgs args)
		{
			this._bIn = false;
			ActivateControlPoints(true);
			this._bControlPoint = ( this._p.Contains(obj) && !this._bResize ) ? false : this._bControlPoint;

			ChangeColor();
		}
		
		protected virtual void Write(string msj)
		{
			if (this._debug) 
			{
				Console.WriteLine(msj);
			}
		}
		
		
		virtual public void CanvasEvent(object obj, Gnome.CanvasEventArgs args)
		{
			
			EventButton ev = new EventButton (args.Event.Handle);
			switch (ev.Type) 
			{
				case EventType.MotionNotify:
					if ( this._bDrag )
					{
						if ( this._bResize )
						{
							this.Resize(obj,ev);
						}
						else
						{
							this.Move(ev);
						}
					}
					break;
					
				case EventType.EnterNotify:
					MouseEnter(obj,args);
					break;
	
					
				case EventType.LeaveNotify:
					MouseLeave(obj,args);
					break;
	
				case EventType.DragEnter:
					
					break;
					
				case EventType.ButtonPress:
					if ( this._bIn )
					{
						this._bDrag = true;
						this._bResize = (this._bControlPoint);
						this._oldPoint.X = (int)ev.X;
						this._oldPoint.Y = (int)ev.Y;
					}
					break;
					
				case EventType.ButtonRelease:
					if ( this._bDrag )
					{
						if ( this._bControlPoint )
						{
							this._bResize = true;
							Console.WriteLine("Resizing");
						}
						else
						{
							this.Move(ev);
						}
					}
					this._bDrag = false;
					break;
			}
			
		}
		
	}
}
